﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NetPE.Core.Metadata;
using NetPE.Core.Metadata.Heaps;
using NetPE.Core.Metadata.Tables;

namespace NetPE.Dialogs
{
    public partial class TokenDialog : Form
    {
        bool refresh = false;
        public TokenDialog(MetadataRow row, MetadataColumn col)
        {
            InitializeComponent();

            refresh = true;

            this.row = row; this.col = col;

            MetadataTokenProvider tkn = row[col.Index] as MetadataTokenProvider;
            Type h = tkn.Container.GetType();

            numericUpDown1.Value = (row[col.Index] as MetadataTokenProvider).Token.Index;
            try
            {
                byte[] obj = null;
                switch ((col.Type as Type).FullName)
                {
                    case "NetPE.Core.Metadata.GUIDToken":
                        {
                            obj = ((Guid)h.GetMethod("GetValue").Invoke(tkn.Container, new object[] { tkn })).ToByteArray();
                        } break;
                    case "NetPE.Core.Metadata.BlobToken":
                        {
                            obj = h.GetMethod("GetValue").Invoke(tkn.Container, new object[] { tkn }) as byte[];
                        } break;
                    case "NetPE.Core.Metadata.USToken":
                        {
                            obj = Encoding.Unicode.GetBytes(h.GetMethod("GetValue").Invoke(tkn.Container, new object[] { tkn }) as string);
                        } break;
                    case "NetPE.Core.Metadata.StringToken":
                        {
                            obj = Encoding.UTF8.GetBytes(h.GetMethod("GetValue").Invoke(tkn.Container, new object[] { tkn }) as string);
                        } break;
                }
                hexEditor1.Object = obj;
            }
            catch
            {
                MessageBox.Show("Wrong Token");
            }
            refresh = false;
        }
        MetadataRow row; MetadataColumn col;

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            if (refresh) return;
            MetadataTokenProvider tkn = row[col.Index] as MetadataTokenProvider;
            Type h = tkn.Container.GetType();
            tkn = (MetadataTokenProvider)h.GetMethod("Resolve").Invoke(tkn.Container, new object[] { new MetadataToken(MetadataTokenType.Unknown, (uint)numericUpDown1.Value) });
            row[col.Index] = tkn;

            try
            {
                byte[] obj = null;
                switch ((col.Type as Type).FullName)
                {
                    case "NetPE.Core.Metadata.GUIDToken":
                        {
                            obj = ((Guid)h.GetMethod("GetValue").Invoke(tkn.Container, new object[] { tkn })).ToByteArray();
                        } break;
                    case "NetPE.Core.Metadata.BlobToken":
                        {
                            obj = h.GetMethod("GetValue").Invoke(tkn.Container, new object[] { tkn }) as byte[];
                        } break;
                    case "NetPE.Core.Metadata.USToken":
                        {
                            obj = Encoding.Unicode.GetBytes(h.GetMethod("GetValue").Invoke(tkn.Container, new object[] { tkn }) as string);
                        } break;
                    case "NetPE.Core.Metadata.StringToken":
                        {
                            obj = Encoding.UTF8.GetBytes(h.GetMethod("GetValue").Invoke(tkn.Container, new object[] { tkn }) as string);
                        } break;
                }
                hexEditor1.Object = obj;
            }
            catch
            {
                MessageBox.Show("Wrong Token");
            }
        }

        private void TokenDialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                switch ((col.Type as Type).FullName)
                {
                    case "NetPE.Core.Metadata.GUIDToken":
                        {
                            GUIDToken tkn = row[col.Index] as GUIDToken;
                            GUIDHeap h = tkn.Container as GUIDHeap;
                            if ((hexEditor1.Object as byte[]).Length != 16) return;
                            h.SetValue(tkn, new Guid(hexEditor1.Object as byte[]));
                            row[col.Index] = tkn;
                        } break;
                    case "NetPE.Core.Metadata.BlobToken":
                        {
                            BlobToken tkn = row[col.Index] as BlobToken;
                            BlobHeap h = tkn.Container as BlobHeap;
                            h.SetValue(tkn, hexEditor1.Object as byte[]);
                            row[col.Index] = tkn;
                        } break;
                    case "NetPE.Core.Metadata.USToken":
                        {
                            USToken tkn = row[col.Index] as USToken;
                            USHeap h = tkn.Container as USHeap;
                            h.SetValue(tkn, Encoding.Unicode.GetString(hexEditor1.Object as byte[]));
                            row[col.Index] = tkn;
                        } break;
                    case "NetPE.Core.Metadata.StringToken":
                        {
                            StringToken tkn = row[col.Index] as StringToken;
                            StringsHeap h = tkn.Container as StringsHeap;
                            h.SetValue(tkn, Encoding.UTF8.GetString(hexEditor1.Object as byte[]));
                            row[col.Index] = tkn;
                        } break;
                }
            }
            catch { }
        }
    }
}
